package com.air.ota.service.imp;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.air.common.util.QueryCondition;
import com.air.common.util.QueryExpression;
import com.air.ota.mo.DepositTrans;
import com.air.ota.mo.InboundMsg;
import com.air.ota.mo.OutboundMsg;
import com.air.ota.service.ICardPwdService;
import com.air.ota.service.IDepositRequestHandlerService;
import com.air.ota.service.IDepositTransService;
import com.air.ota.service.IEpayService;
import com.air.ota.service.ILastDepositTransHandlerService;
import com.air.ota.service.IOutboundMsgService;
import com.air.ota.service.IPkgSequenceService;
import com.air.ota.service.ISMGPService;
import com.air.ota.util.AppConstant;
import com.air.ota.util.HexStringUtil;
import com.air.ota.util.SZTInterface;
import com.air.ota.vo.SZTBaseResponseVO;
import com.air.ota.vo.SZTDepositReqTransVO;
import com.air.ota.vo.SZTDepositRequestVO;
import com.air.ota.vo.SZTDepositResTransVO;
import com.air.ota.vo.UTKBaseDownlinkVO;
import com.air.ota.vo.UTKDepositRequestUplinkVO;
import com.air.ota.vo.UTKDepositResponseDownlinkVO;

@Service("depositRequestHandlerService")
public class DepositRequestHandlerServiceImp implements
		IDepositRequestHandlerService {
	
	@Autowired
	IDepositTransService depositTransService;
	@Autowired
	IOutboundMsgService outboundMsgService;
	@Autowired
	IEpayService epayService;
	@Autowired
	IPkgSequenceService pkgSequenceService;
	@Autowired
	ILastDepositTransHandlerService lastDepositTransHandlerService;
	@Autowired
	ICardPwdService cardPwdService;
	@Autowired
	ISMGPService smgpService;
	
	@Override
	public void process(UTKDepositRequestUplinkVO pkgVO, InboundMsg inboundMsg) throws Exception {
		System.out.println("------------Ready to Process Deposit Request");
		byte utkResponseResult = 0x00;
		
		if (processDuplicateRequest(pkgVO,inboundMsg)){
			System.out.println("------------ Process Duplicate Deposit Request");
			return;
		}
		
		
		//处理上一笔充值记录
		lastDepositTransHandlerService.process(pkgVO.getLastHistoryTrans(),inboundMsg.getPhoneNumber());
		
		SimpleDateFormat sdf  = new SimpleDateFormat("yyyyMMddHHmmss");
		Date triggerTime = new Date();
		String deviceTriggerTime=sdf.format(triggerTime);
		
		//byte[] depositInfoFile = this.updateDepositInfoFile(HexStringUtil.bytesToHexString(pkgVO.getDepositInfoFile()), deviceTriggerTime);
		
		byte[] depositInfoFile = pkgVO.getDepositInfoFile();
		pkgVO.setDepositInfoFile(depositInfoFile);
		
		DepositTrans trans = new DepositTrans();
		trans.setSztId("00000000");
		trans.setCellphone(inboundMsg.getPhoneNumber());
		trans.setTransDate(System.currentTimeMillis());
		trans.setDepositSequence(HexStringUtil.bytesToHexString(pkgVO.getDepositSequence()));
		trans.setResult(AppConstant._transResult_processing);
		trans.setCardAppSequence(HexStringUtil.bytesToHexString(pkgVO.getCardAppSequence()));
		trans.setDepositType(HexStringUtil.byteToHexString(pkgVO.getDepositType()));
		trans.setCardRandom(HexStringUtil.bytesToHexString(pkgVO.getCardRandom()));
		trans.setKeyIndex(HexStringUtil.byteToHexString(pkgVO.getKeyIndex()));
		trans.setEwalletTransSequence(HexStringUtil.bytesToHexString(pkgVO.getEwalletTransSequence()));
		trans.setEwalletRemain(HexStringUtil.bytesToHexString(pkgVO.getEwalletRemain()));
		trans.setAmount(HexStringUtil.bytesToHexString(pkgVO.getAmount()));
		trans.setTerminalCode(HexStringUtil.bytesToHexString(pkgVO.getTerminalCode()));
		trans.setMac1(HexStringUtil.bytesToHexString(pkgVO.getMac1()));
		trans.setDepositInfoFile(HexStringUtil.bytesToHexString(pkgVO.getDepositInfoFile()));
		trans.setLastTransData(HexStringUtil.bytesToHexString(pkgVO.getLastTransData()));
		trans.setCardType(HexStringUtil.byteToHexString(pkgVO.getCardType()));
		trans.setOnlinePayPwd(HexStringUtil.bytesToHexString(pkgVO.getPayPwdOrTriggerSequence()));
		trans.setDeviceTriggerTime(deviceTriggerTime);
		
		depositTransService.insertOrUpdate(trans);
		
		boolean pwdAuthResult=cardPwdService.auth(inboundMsg.getPhoneNumber(), pkgVO.getPassword());
		System.out.println("pwd="+pkgVO.getPassword()+"   pwdAuthResult="+pwdAuthResult);
		//trans = depositTransService.findById(1018);
		//deviceTriggerTime = trans.getDeviceTriggerTime();
		if (!pwdAuthResult){
			pwdAuthFailureHandler(trans,pkgVO);
			return;
		}
		
		
		//调用电信翼支付接口
		String amountHexStr=HexStringUtil.bytesToHexString(pkgVO.getAmount());
		int amount=Integer.parseInt(amountHexStr, 16);
		//"13318258474"
		//boolean epayResult  =true; 
		//boolean epayResult = epayService.charge(amount,"13360518103",trans.getId()+"");
		String epayResultCode = epayService.charge(amount, trans.getCellphone(),trans.getId()+"");
		System.out.println("EPAY RESULT_Code="+epayResultCode);
		if ("0".equals(epayResultCode)){//翼支付成功
			System.out.println("EPAY CHARGE SUCCESS");
			trans.setResult(AppConstant._depositResult_epayCharge_success);
			depositTransService.updateById(trans);
		}else{//翼支付失败
			System.out.println("EPAY CHARGE FAILURE");
			epayChargeFailureHandler(trans,pkgVO,epayResultCode);
			return;
		}
		
		//调用深圳通接口
		byte[] deviceSequence = HexStringUtil.hexStringToBytes(trans.getDeviceSequence());
		byte[] sztSequence = HexStringUtil.hexStringToBytes(trans.getSztId());
		byte[] sumDeviceTransFee = HexStringUtil.hexStringToBytes("00000000");
		
		SZTDepositReqTransVO sztDepositReqTransVO = new SZTDepositReqTransVO(deviceSequence,sztSequence,deviceTriggerTime,
				HexStringUtil.hexStringToByte(trans.getKeyIndex()),
				HexStringUtil.hexStringToBytes(trans.getCardAppSequence()),
				HexStringUtil.hexStringToBytes(trans.getCardRandom()),
				HexStringUtil.hexStringToBytes(trans.getEwalletTransSequence()),
				HexStringUtil.hexStringToBytes(trans.getEwalletRemain()),
				HexStringUtil.hexStringToBytes(trans.getAmount()),
				pkgVO.getTransTypeTag(),
				HexStringUtil.hexStringToBytes(trans.getTerminalCode()),
				HexStringUtil.hexStringToBytes(trans.getMac1()),
				HexStringUtil.hexStringToBytes(trans.getDepositInfoFile()),
				HexStringUtil.hexStringToBytes(trans.getLastTransData()),
				sumDeviceTransFee);
		
		SZTDepositRequestVO sztDepositRequestVO  = new SZTDepositRequestVO(sztDepositReqTransVO.getTransDataHexString());
		SZTInterface sztInterface = new SZTInterface();
		//System.out.println(sztDepositReqTransVO.getTransDataHexString());
		byte[] response=sztInterface.sendRequest(HexStringUtil.hexStringToBytes(sztDepositRequestVO.getMsgPackage()));
		SZTBaseResponseVO responseVO = new SZTBaseResponseVO();
		responseVO.parse(response);
		
		SZTDepositResTransVO sztDepositResTransVO = new SZTDepositResTransVO();
		sztDepositResTransVO.parse(HexStringUtil.hexStringToBytes(responseVO.getData()));
		
		//更新DepositTrans对象
		if (sztDepositResTransVO.getTransResult()==0x00){//Success
			trans.setResult(AppConstant._depositResult_sztRequest_success);
			trans.setSztId(HexStringUtil.bytesToHexString(sztDepositResTransVO.getSztSequence()));
			trans.setMac2(HexStringUtil.bytesToHexString(sztDepositResTransVO.getMac2()));
			trans.setSztTriggerTime(sztDepositResTransVO.getTransDate());
			depositTransService.updateById(trans);
			System.out.println("SZT DepositResponse success");
		}else{
			System.out.println("SZT DepositResponse ERROR CODE="+HexStringUtil.byteToHexString(sztDepositResTransVO.getTransResult()));
			sztRequestFailureHandler(trans,pkgVO);
			return;
		}
		
		//Build UTK Deposit Response Pkg
		
		UTKDepositResponseDownlinkVO depositResponseDownlinkVO = 
			new UTKDepositResponseDownlinkVO(
					pkgVO.getCardSequence(),pkgSequenceService.getNextSequence(trans.getCellphone()),
					HexStringUtil.hexStringToBytes(trans.getCardAppSequence()),
					HexStringUtil.hexStringToBytes(trans.getDepositSequence()),
					utkResponseResult,
					null,
					HexStringUtil.hexStringToBytes(trans.getDeviceTriggerTime()),
					HexStringUtil.hexStringToBytes(trans.getMac2())
			);
		byte[] responsePkg=depositResponseDownlinkVO.buildPkg();
		
		OutboundMsg outboundMsg = new OutboundMsg();
		outboundMsg.setContent(HexStringUtil.bytesToHexString(responsePkg));
		outboundMsg.setDest(0);
		outboundMsg.setPhoneNumber(trans.getCellphone());
		outboundMsg.setSendDate(System.currentTimeMillis());
		outboundMsg.setTransId(trans.getId());
		outboundMsg.setNeedRetry(1);
		outboundMsg.setMsgType(AppConstant._outbound_msg_type_depositResponse);
		outboundMsgService.insert(outboundMsg);
		
	}
	
	/*private byte[] updateDepositInfoFile(String rawString,String deviceTriggerTime){
		String prefix=rawString.substring(0, 34);
		String suffix=rawString.substring(48);
		
		return HexStringUtil.hexStringToBytes(prefix+deviceTriggerTime+suffix);
	}*/
	
	private void pwdAuthFailureHandler(DepositTrans trans,UTKDepositRequestUplinkVO pkgVO) throws Exception{
		trans.setMac2("00000000");
		trans.setResult(AppConstant._depositResult_pwdAuth_failure);
		byte utkResponseResult = 0x01;
		depositTransService.updateById(trans);
		
		String errorDesc = "充值失败！服务密码错误，请重试";
		byte[] descBytes=errorDesc.getBytes("utf-16BE");
		
		UTKDepositResponseDownlinkVO depositResponseDownlinkVO = 
			new UTKDepositResponseDownlinkVO(
					pkgVO.getCardSequence(),pkgSequenceService.getNextSequence(trans.getCellphone()),
					HexStringUtil.hexStringToBytes(trans.getCardAppSequence()),
					HexStringUtil.hexStringToBytes(trans.getDepositSequence()),
					utkResponseResult,
					descBytes,
					HexStringUtil.hexStringToBytes(trans.getDeviceTriggerTime()),
					HexStringUtil.hexStringToBytes(trans.getMac2())
			);
		byte[] responsePkg=depositResponseDownlinkVO.buildPkg();
		
		OutboundMsg outboundMsg = new OutboundMsg();
		outboundMsg.setContent(HexStringUtil.bytesToHexString(responsePkg));
		outboundMsg.setDest(0);
		outboundMsg.setPhoneNumber(trans.getCellphone());
		outboundMsg.setSendDate(System.currentTimeMillis());
		outboundMsg.setTransId(trans.getId());
		outboundMsg.setNeedRetry(0);
		outboundMsg.setMsgType(AppConstant._outbound_msg_type_depositResponse);
		outboundMsgService.insert(outboundMsg);
		
		this.smgpService.sendTxtSMS(trans.getCellphone(), "充值失败！服务密码错误，请重试");
	}
	
	private void epayChargeFailureHandler(DepositTrans trans,UTKDepositRequestUplinkVO pkgVO,String epayResultCode) throws Exception{
		trans.setMac2("00000000");
		trans.setResult(AppConstant._depositResult_epayCharge_failure);
		byte utkResponseResult = 0x01;
		depositTransService.updateById(trans);
		
		String errorDesc = "充值失败！扣款失败，请重试";
		byte[] descBytes=errorDesc.getBytes("utf-16BE");
		
		UTKDepositResponseDownlinkVO depositResponseDownlinkVO = 
			new UTKDepositResponseDownlinkVO(
					pkgVO.getCardSequence(),pkgSequenceService.getNextSequence(trans.getCellphone()),
					HexStringUtil.hexStringToBytes(trans.getCardAppSequence()),
					HexStringUtil.hexStringToBytes(trans.getDepositSequence()),
					utkResponseResult,
					descBytes,
					HexStringUtil.hexStringToBytes(trans.getDeviceTriggerTime()),
					HexStringUtil.hexStringToBytes(trans.getMac2())
			);
		byte[] responsePkg=depositResponseDownlinkVO.buildPkg();
		
		OutboundMsg outboundMsg = new OutboundMsg();
		outboundMsg.setContent(HexStringUtil.bytesToHexString(responsePkg));
		outboundMsg.setDest(0);
		outboundMsg.setPhoneNumber(trans.getCellphone());
		outboundMsg.setSendDate(System.currentTimeMillis());
		outboundMsg.setTransId(trans.getId());
		outboundMsg.setNeedRetry(0);
		outboundMsg.setMsgType(AppConstant._outbound_msg_type_depositResponse);
		outboundMsgService.insert(outboundMsg);
		
		
		if ("10062151".equals(epayResultCode)){//资金不足
			this.smgpService.sendTxtSMS(trans.getCellphone(), "充值失败！您的翼支付账户余额不足，请登录www.bestpay.com.cn为翼支付账户充值");
			return;
		}else{
			this.smgpService.sendTxtSMS(trans.getCellphone(), "充值失败！扣款失败，请重试");
		}
		
	}
	
	private void sztRequestFailureHandler(DepositTrans trans,UTKDepositRequestUplinkVO pkgVO) throws Exception{
		trans.setResult(AppConstant._depositResult_sztRequest_failure);
		trans.setMac2("00000000");
		depositTransService.updateById(trans);
		byte utkResponseResult = 0x01;
		epayService.refund(trans);
		
		String errorDesc = "充值失败！深圳通请求失败";
		byte[] descBytes=errorDesc.getBytes("utf-16BE");
		
		UTKDepositResponseDownlinkVO depositResponseDownlinkVO = 
			new UTKDepositResponseDownlinkVO(
					pkgVO.getCardSequence(),pkgSequenceService.getNextSequence(trans.getCellphone()),
					HexStringUtil.hexStringToBytes(trans.getCardAppSequence()),
					HexStringUtil.hexStringToBytes(trans.getDepositSequence()),
					utkResponseResult,
					descBytes,
					HexStringUtil.hexStringToBytes(trans.getDeviceTriggerTime()),
					HexStringUtil.hexStringToBytes(trans.getMac2())
			);
		byte[] responsePkg=depositResponseDownlinkVO.buildPkg();
		
		OutboundMsg outboundMsg = new OutboundMsg();
		outboundMsg.setContent(HexStringUtil.bytesToHexString(responsePkg));
		outboundMsg.setDest(0);
		outboundMsg.setPhoneNumber(trans.getCellphone());
		outboundMsg.setSendDate(System.currentTimeMillis());
		outboundMsg.setTransId(trans.getId());
		outboundMsg.setNeedRetry(0);
		outboundMsg.setMsgType(AppConstant._outbound_msg_type_depositResponse);
		outboundMsgService.insert(outboundMsg);
		
		this.smgpService.sendTxtSMS(trans.getCellphone(), "充值失败！系统错误。");
	}
	
	private boolean processDuplicateRequest(UTKDepositRequestUplinkVO pkgVO, InboundMsg inboundMsg) throws Exception{
		boolean isDuplicate = false;
		
		QueryCondition condition = new QueryCondition();
		condition.addQueryCondition("depositSequence",HexStringUtil.bytesToHexString(pkgVO.getDepositSequence()), QueryExpression.EQUALS);
		condition.addQueryCondition("cellphone",inboundMsg.getPhoneNumber() , QueryExpression.EQUALS);
		List<DepositTrans> result= this.depositTransService.queryByCondition(condition);
		
		if (result!=null&&result.size()>0){//update
			isDuplicate = true;
			DepositTrans trans = result.get(0);
			
			QueryCondition condition2 = new QueryCondition();
			condition2.addQueryCondition("transId", trans.getId(), QueryExpression.EQUALS);
			condition2.addQueryCondition("msgType", AppConstant._outbound_msg_type_depositResponse, QueryExpression.EQUALS);
			List<OutboundMsg> msgList=outboundMsgService.queryByCondition(condition2);
			if(msgList!=null&&msgList.size()>0){
				OutboundMsg msg = msgList.get(0);
				
				UTKBaseDownlinkVO newDownlinVO = UTKBaseDownlinkVO.updatePkgSequence(pkgVO.getCardSequence(),
						pkgSequenceService.getNextSequence(trans.getCellphone()), msg.getContent());
				
				msg.setContent(HexStringUtil.bytesToHexString(newDownlinVO.buildPkg()));
				msg.setNeedRetry(1);
				System.out.println("Ready to Send Duliplcate Deposit Resut DownLink,TransId="+trans.getId()+", outbound msgId="+msg.getId());
				this.outboundMsgService.updateById(msg);
				UTKBaseDownlinkVO.decrpytDownlinkSMS(msg.getContent(), pkgVO.getCardSequence());
				/*if (msg.getNeedRetry() == 0){
					
					
					
				}*/
			}
		}
		return isDuplicate;
	}

}
